home *** CD-ROM | disk | FTP | other *** search
- /* Miscellaneous system dependent routines for splitsh */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <signal.h>
-
-
- #ifdef HAVE_TERMIO_H
- #include <termio.h>
- #else
- #include <sys/ioctl.h>
- #endif /* HAVE_TERMIO_H */
-
- #ifdef HAVE_BSDTTY_H
- #include <sys/bsdtty.h>
- #ifndef TIOCNOTTY
- #define TIOCNOTTY _IO('t', 113) /* HP-UX void tty definition */
- #endif
- #endif /* HAVE_BSDTTY_H */
-
- #ifdef NEED_INET_H
- /*#define STTY_HACK*/
- #endif
-
- /*
- * Initialize a pty, fork a command running under it, and then
- * return the master file descriptor
- */
-
- extern int WU_lines, WL_lines, W_columns; /* From vt100.c */
-
- #define UPPER 0 /* Upper window definition */
- #define LOWER 1 /* Lower window definition */
-
- int pty_open(argv, childpid, win)
- char *argv[];
- int *childpid;
- int win; /* 0 for upper, 1 for lower */
- {
-
- void dropctty(), pty_setwin();
- int get_master_pty(), get_slave_pty();
- char *get_ttyname(), *myputenv();
-
- char LINES[12], COLUMNS[12], SPLITVT[24];
- int returnfd, slave_fd;
-
- /* Get the master pty file descriptor */
- if ( (returnfd=get_master_pty()) < 0 )
- return(-1);
-
- /* Fork and go! */
- if ( ((*childpid)=fork()) < 0 )
- return(-1);
- else if ( (*childpid) == 0 )
- {
- dropctty(); /* Lose controlling tty */
-
- if ( (slave_fd=get_slave_pty()) < 0 )
- {
- perror("Can't open slave tty");
- exit(128);
- }
- close(0); close(1); close(2);
- dup(slave_fd); dup(slave_fd); dup(slave_fd);
- close(slave_fd); close(returnfd);
-
- /* Reattatch the new tty as the controlling terminal */
- /* Under old UNIX, just opening the new tty after
- losing the controlling tty is good enough.
- Under newer Unices, it requires an ioctl(). */
- #ifdef TIOCSCTTY
- (void) ioctl(0, TIOCSCTTY, 0);
- #endif
-
- /* Set the lines and columns on the new tty */
- #ifdef TIOCGWINSZ /* We don't want to set the environment if possible */
- pty_setwin(0, win);
- #else
- if ( win == UPPER )
- sprintf(LINES, "LINES=%d", WU_lines);
- else
- sprintf(LINES, "LINES=%d", WL_lines);
- myputenv(LINES);
- sprintf(COLUMNS, "COLUMNS=%d", W_columns);
- myputenv(COLUMNS);
- #endif /* TIOCGWINSZ */
- /* Set the SPLITVT environment variable for shell scripts */
- if ( win == UPPER )
- sprintf(SPLITVT, "SPLITVT=upper");
- else
- sprintf(SPLITVT, "SPLITVT=lower");
- myputenv(SPLITVT);
- myputenv("TERM=vt100"); /* Put the new TERM in the env. */
-
- #ifdef SIGTSTP
- signal(SIGTSTP, SIG_IGN);
- #endif
- #ifdef STTY_HACK
- system("stty sane echo echoe intr '^C' erase '^H'");
- #else
- (void) tty_reset(0);
- #endif
- /* "touch" the tty so 'w' reports proper idle times */
- (void) utime(get_ttyname(), NULL);
-
- /* Set our uid to our real uid if necessary */
- (void) setuid(getuid());
-
- /* Run the requested program, with possible leading dash. */
- execvp(((*argv[0] == '-') ? argv[0]+1 : argv[0]), argv);
- perror(argv[0]);
- exit(255);
- }
- return(returnfd);
- }
-
-
-
- /*
- * Pseudo-terminal routines for Unix System V Release 3.2 and BSD4.2-3
- */
-
-
- extern int errno;
- int master_fd;
-
- char tty_name[64]={'\0'};
- char pty_name[64]={'\0'};
-
- char *get_ttyname()
- {
- if ( tty_name[0] )
- return(tty_name);
- return(NULL);
- }
-
- #ifdef IRIX /* IRIX System V for SGI machines */
-
- extern char *_getpty();
-
- int get_master_pty()
- {
-
- char *ttyptr;
-
- if ( (ttyptr=_getpty(&master_fd, O_RDWR, 0600, 0)) == 0 )
- return(-1);
- else
- strcpy(tty_name, ttyptr);
-
- return(master_fd);
- }
-
- /*
- * Open the slave half of a pseudo-terminal.
- */
-
- int get_slave_pty()
- {
- int slave_fd;
- char *slavename;
-
- slavename=tty_name;
-
- if (slavename == NULL) {
- close(master_fd);
- return(-1);
- }
-
- if ( (slave_fd=open(slavename, O_RDWR)) < 0 ) /* open the slave */
- {
- close(master_fd);
- return(-1);
- }
-
- return(slave_fd);
- }
- #else /* ! IRIX */
-
-
- #ifdef SOLARIS /* System V.4 pty routines from W. Richard Stevens */
-
- #include <stropts.h>
-
- #define DEV_CLONE "/dev/ptmx"
-
- extern char *ptsname();
-
- int get_master_pty()
- {
-
- char *ttyptr;
-
- if ( (master_fd=open(DEV_CLONE, O_RDWR)) < 0 )
- return(-1);
-
- if ( grantpt(master_fd) < 0 ) /* grant access to slave */
- {
- close(master_fd);
- #ifdef DEBUG
- perror("grantpt()");
- #endif
- return(-1);
- }
-
- if ( unlockpt(master_fd) < 0 ) /* clear slave's lock flag */
- {
- close(master_fd);
- return(-1);
- }
-
- if ( (ttyptr=ptsname(master_fd)) == NULL )
- {
- close(master_fd);
- return(-1);
- }
- else
- strcpy(tty_name, ttyptr);
-
- return(master_fd);
- }
-
- /*
- * Open the slave half of a pseudo-terminal.
- */
-
- int get_slave_pty()
- {
- int slave_fd;
- char *slavename;
-
- slavename=tty_name;
-
- if ( (slave_fd=open(slavename, O_RDWR)) < 0 ) /* open the slave */
- {
- close(master_fd);
- return(-1);
- }
-
- if ( ioctl(slave_fd, I_PUSH, "ptem") < 0 )
- {
- close(master_fd);
- close(slave_fd);
- return(-1);
- }
-
- if ( ioctl(slave_fd, I_PUSH, "ldterm") < 0 )
- {
- close(master_fd);
- close(slave_fd);
- return(-1);
- }
-
- if ( ioctl(slave_fd, I_PUSH, "ttcompat") < 0 )
- {
- close(master_fd);
- close(slave_fd);
- return(-1);
- }
-
- return(slave_fd);
- }
-
- #else /* BSD, Sun/OS, AIX, ULTRIX, HP-UX, AT&T SYSV */
-
- #include <setjmp.h>
-
- #ifndef X_OK
- #define R_OK 4 /* Test for Read permission */
- #define W_OK 2 /* Test for Write permission */
- #define X_OK 1 /* Test for eXecute permission */
- #endif /* X_OK */
-
- jmp_buf next;
-
- void trynext()
- {
- longjmp(next, 2);
- }
-
-
- int get_master_pty()
- {
- int i, master_fd;
- char *ptr;
- struct stat statbuff;
- #ifdef PTYCHAR
- static char ptychar[]=PTYCHAR; /* X */
- static char hexdigit[]=HEXDIGIT; /* Y */
- #else
- static char ptychar[]="pqrstuvwxyzPQRST"; /* X */
- static char hexdigit[]="0123456789abcdef"; /* Y */
- #endif
-
- for (ptr=ptychar; *ptr != 0; ptr++)
- {
- strcpy(pty_name, "/dev/ptyXY");
- pty_name[8]=(*ptr); /* X */
- pty_name[9]='0'; /* Y */
-
- if ( stat(pty_name, &statbuff) < 0 )
- break;
- #ifdef OLDDEBUG
- fprintf(stderr, "statted.\n");
- #endif
- i=(-1); /* Initialize i */
-
- /* Set a time limit for the open */
- if ( setjmp(next) == -1 )
- return(-1);
- signal(SIGALRM, trynext);
-
- for ( ++i; hexdigit[i]; ++i)
- {
- pty_name[5]='p';
- pty_name[9]=hexdigit[i];
-
- alarm(2); /* Set an open timeout */
-
- if ( (master_fd=open(pty_name, O_RDWR)) >= 0 )
- {
- alarm(0); /* Reset the alarm */
-
- pty_name[5]='t';
- sprintf(tty_name, "%s", pty_name);
- #ifdef OLDDEBUG
- fprintf(stderr, "tty: %s\n", tty_name);
- #endif
- if ( access(tty_name, R_OK|W_OK) == 0 ) {
- signal(SIGALRM, SIG_DFL);
- return (master_fd);
- } else {
- pty_name[5]='p';
- (void) close(master_fd);
- }
- }
- /* reset the alarm */
- alarm(0);
- }
- }
- return(-1);
- }
-
-
- /* Open the slave half of a pseudo-terminal. */
-
- int get_slave_pty()
- {
- int slave_fd;
-
- if ( (slave_fd=open(tty_name, O_RDWR)) < 0 )
- {
- close(master_fd);
- return(-1);
- }
- return(slave_fd);
- }
-
- #endif /* if SOLARIS */
- #endif /* if IRIX */
-
-
- /* These are the binary data functions that I am using instead of
- bcopy() and bzero(), written by Richard A. O'Keefe.
- Thanks!
- */
-
- void d_copy(src, dst, len)
- register char *src, *dst;
- register int len;
- {
- while (--len >= 0) *dst++ = *src++;
- }
-
- void d_zero(dst, len)
- register char *dst;
- register int len;
- {
- while (--len >= 0) *dst++ = 0;
- }
-
-
-
- /* Here are the Terminal manipulation routines... */
-
-
- /* Code to disassociate from my tty. Yay! :) */
-
- void dropctty()
- {
- int fd;
-
- #if defined(_POSIX_SOURCE) || defined(SOLARIS)
- setsid(); /* The POSIX solution is simple. :) */
- #else
- #ifdef TIOCNOTTY /* We want to get HP-UX, BSD, and Sun/OS here */
- setpgrp(0, 0);
-
- #ifndef CIBAUD /* Sun/OS doesn't need to do TIOCNOTTY. */
- if ( (fd=open("/dev/tty", O_RDWR)) > (-1) )
- {
- if (ioctl(fd, TIOCNOTTY, 0) < 0)
- {
- perror("ioctl TIOCNOTTY error");
- fprintf(stderr, "\r");
- }
- close(fd);
- }
- #endif /* CIBAUD */
- #else /* SYSV */
- setpgrp();
- #endif /* TIOCNOTTY */
- #endif /* _POSIX_SOURCE */
- }
-
-
- #ifdef HAVE_TERMIO_H
-
- /* Get the modes of the controlling tty and save them. Saves
- ttymodes in tty_mode and returns -1 if ioctl fails. */
-
- struct termio tty_mode; /* Save tty mode here */
- static int tty_init=0;
-
- int tty_getmode(fd)
- int fd;
- {
- d_zero((char *)&tty_mode, sizeof(struct termio));
- tty_init=1; /* Flag: we have initialized the tty_mode struct */
-
- if ( ! isatty(fd) )
- return(0);
-
- #ifdef OLDDEBUG
- fprintf(stderr, "Getting tty modes for tty_mode.\r\n");
- #endif
-
- if (ioctl(fd, TCGETA, (char *) &tty_mode) < 0)
- {
- #ifdef DEBUG
- perror("tty_getmode(): ioctl error");
- #endif
- return(-1);
- }
-
- return(0);
- }
-
-
- /* Set a tty to a sane mode */
-
- int tty_sane(fd)
- int fd;
- {
- struct termio temp_mode;
-
- if ( ! isatty(fd) )
- return(0);
-
- if ( ! tty_init )
- {
- if (ioctl(fd, TCGETA, (char *) &tty_mode) < 0)
- return(-1);
- }
-
- #ifdef SEVEN_BIT
- temp_mode.c_iflag=(tty_mode.c_iflag|(BRKINT|IGNPAR|ISTRIP|ICRNL|IXON));
- temp_mode.c_oflag=(tty_mode.c_oflag|(OPOST|ONLCR));
- #else
- temp_mode.c_iflag=(tty_mode.c_iflag|(BRKINT|IGNPAR|ICRNL|IXON));
- temp_mode.c_cflag=(tty_mode.c_cflag|(CS8|CREAD));
- #endif
- temp_mode.c_lflag=(tty_mode.c_lflag|(ISIG|ICANON|ECHO|ECHOE|ECHOK));
- temp_mode.c_cflag=(tty_mode.c_cflag|(CS7|PARENB|CREAD));
- temp_mode.c_cc[VERASE]=('H'^64);
- temp_mode.c_cc[VKILL]=('U'^64);
- temp_mode.c_cc[VQUIT]=('\\'^64);
- temp_mode.c_cc[VINTR]=('C'^64);
- temp_mode.c_cc[VEOF]=('D'^64);
-
- /* TCSETAW is important for letting tty input drain. */
- if ( ioctl(fd, TCSETAW, (char *)&temp_mode) < 0 )
- {
- #ifdef DEBUG
- perror("Can't set tty modes");
- #endif
- return(-1);
- }
-
- return(0);
- }
-
-
- /* Set a terminal in raw mode */
-
- int tty_raw(fd)
- int fd; /* of tty device */
- {
- struct termio temp_mode;
-
- if ( ! tty_init )
- return(-1);
-
- if ( ! isatty(fd) )
- return(0);
-
- if ( ioctl(fd, TCGETA, (char *)&temp_mode) < 0 )
- return(-1);
-
- #ifdef SEVEN_BIT
- temp_mode.c_iflag=(IGNBRK | ISTRIP); /* turn off all input control */
- #else
- temp_mode.c_iflag=(IGNBRK); /* turn off all input control */
- #endif
- temp_mode.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONLRET);
- /* disable output post-processing */
- temp_mode.c_lflag = 0;
- temp_mode.c_cc[VMIN]=1; /* 1 or more chars satisfy read */
- temp_mode.c_cc[VTIME]=0; /* 10'ths of seconds between chars */
-
- /* TCSETAW is important for letting tty input drain. */
- if (ioctl(fd, TCSETAW, (char *) &temp_mode) < 0)
- return(-1);
- return(0);
- }
-
-
- /* Restore terminal's mode to whatever it was on the most
- recent call to the tty_getmode() function. */
-
- int tty_reset(fd)
- int fd;
- {
- if ( ! tty_init )
- return(-1);
-
- if ( ! isatty(fd) )
- return(0);
-
- /* TCSETAW is important for letting tty input drain. */
- if (ioctl(fd, TCSETAW, (char *) &tty_mode) < 0)
- return(-1);
- return(0);
- }
-
- #else /* no /usr/include/termio.h */
- #ifdef NEED_COMPAT_H /* FreeBSD needs this */
- #include <sys/ioctl_compat.h>
- #endif /* NEED_COMPAT_H */
-
- /* Set a tty to a sane mode */
-
- int tty_sane(fd)
- int fd;
- {
- struct sgttyb temp_mode;
-
- if ( ! isatty(fd) )
- return(0);
-
- if (ioctl(fd, TIOCGETP, (char *) &temp_mode) < 0)
- return(-1);
-
- temp_mode.sg_flags|=ECHO;
-
- if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0)
- return(-1);
-
- return(0);
- }
-
-
-
- /* Get the modes of the controlling tty and save them. Saves
- ttymodes in tty_mode and returns 1 if ioctl fails. */
-
- static struct sgttyb tty_mode; /* save tty mode here */
-
- int tty_getmode(fd)
- int fd;
- {
- if ( ! isatty(fd) )
- return(0);
-
- if (ioctl(fd, TIOCGETP, (char *) &tty_mode) < 0)
- return(-1);
-
- return(0);
- }
-
- /*
- * Put a terminal device into RAW mode with ECHO off.
- * Before doing so we first save the terminal's current mode,
- * assuming the caller will call the tty_reset() function
- * (also in this file) when it's done with raw mode.
- */
-
- int tty_raw(fd)
- int fd; /* of terminal device */
- {
- struct sgttyb temp_mode;
-
- if ( ! isatty(fd) )
- return(0);
-
- temp_mode = tty_mode;
-
- temp_mode.sg_flags |= RAW; /* turn RAW mode on */
- temp_mode.sg_flags &= ~ECHO; /* turn ECHO off */
- if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0)
- return(-1);
-
- return(0);
- }
-
- /*
- * Restore a terminal's mode to whatever it was on the most
- * recent call to the tty_getmode() function above.
- */
-
- int tty_reset(fd)
- int fd; /* of terminal device */
- {
- if ( ! isatty(fd) )
- return(0);
-
- if (ioctl(fd, TIOCSETP, (char *) &tty_mode) < 0)
- return(-1);
-
- return(0);
- }
- #endif /* HAVE_TERMIO_H */
-
-
- /* Set the pty window size to the size of the virtual window */
-
- #ifdef TIOCSWINSZ
-
- static struct /* winsize */ {
- unsigned short ws_row; /* rows, in characters */
- unsigned short ws_col; /* columns, in characters */
- unsigned short ws_xpixel; /* horizontal size - not used */
- unsigned short ws_ypixel; /* vertical size - not used */
- } mywinz;
-
- void pty_setwin(fd, win)
- int fd; /* The pty file descriptor */
- int win; /* 0 for upper, 1 for lower window */
- {
- if ( win == UPPER )
- mywinz.ws_row=WU_lines;
- else
- mywinz.ws_row=WL_lines;
- mywinz.ws_col=W_columns;
- mywinz.ws_xpixel=0;
- mywinz.ws_ypixel=0;
- (void) ioctl(fd, TIOCSWINSZ, &mywinz);
- }
-
- #else
- void pty_setwin(fd, win)
- int fd;
- int win;
- {
- /* Bogus routine */
- }
- #endif /* TIOCSWINSZ */
-
- /*
- * Write "n" bytes to a descriptor.
- * Use in place of write() when fd is a stream socket.
- */
-
- int writen(fd, ptr, nbytes)
- register int fd;
- register char *ptr;
- register int nbytes;
- {
- int nleft, nwritten;
-
- nleft = nbytes;
- while (nleft > 0) {
- nwritten = write(fd, ptr, nleft);
- if (nwritten <= 0)
- return(nwritten); /* error */
-
- nleft -= nwritten;
- ptr += nwritten;
- }
- return(nbytes - nleft);
- }
-
-
- /*
- A function to put strings in the environment using malloc().
- Returns a pointer to the environment string or NULL if malloc() fails.
- */
-
- char *myputenv(string)
- char *string;
- {
- extern char **environ; /* The process environment strings */
-
- char *newptr, **envptr;
- char *tmptr, temp[BUFSIZ];
- int distance, n=0;
-
- for ( distance=0; ((*(string+distance)) &&
- ((*(string+distance)) != '=')); ++distance );
- if ( ! (*(string+distance)) )
- return(NULL);
- else
- ++distance;
-
- if ( (newptr=(char *)malloc(strlen(string)+1)) == NULL )
- return(NULL);
- else
- strcpy(newptr, string);
-
- for ( envptr=environ; *envptr; ++envptr, ++n ) {
- if ( strncmp(*envptr, string, distance) == 0 ) {
- *envptr=newptr;
- return(newptr);
- }
- }
-
- *envptr=newptr;
- ++envptr;
- *envptr=NULL;
-
- return(newptr);
- }
-
-
- /* * * * * * * Routines to parse a line into an array of tokens * * * * * * */
-
- static int istoken(c, tokens)
- char c;
- char *tokens;
- {
- while ( *tokens ) {
- if ( c == *(tokens++) )
- return(1);
- }
- return(0);
- }
-
- /* This version of tokenize is destructive to the line it parses. */
-
- void tokenize(array, line, tokens)
- char *array[];
- char *line;
- char *tokens;
- {
- char *head, *ptr;
- int i=0;
-
- for ( head=line; *line; ) {
- if ( istoken(*line, tokens) ) {
- *(line++)='\0';
- array[i++]=head;
- while ( istoken(*line, tokens) )
- ++line;
- head=line;
- } else
- ++line;
- }
- array[i++]=head;
- array[i]=NULL;
- }
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-